﻿#region License
// Copyright 2010 Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using MediaWiki.Common;
using Microsoft.Win32;

namespace MediaWiki.MediaWikiConverter.Utilities.Registry
{
  public static class RegistryEx
  {
    public static readonly RegistryKeyEx ClassesRoot = new RegistryKeyEx(RegistryHive.ClassesRoot, "HKEY_CLASSES_ROOT");
    public static readonly RegistryKeyEx CurrentConfig = new RegistryKeyEx(RegistryHive.CurrentConfig, "HKEY_CURRENT_CONFIG");
    public static readonly RegistryKeyEx CurrentUser = new RegistryKeyEx(RegistryHive.CurrentUser, "HKEY_CURRENT_USER");
    public static readonly RegistryKeyEx DynData = new RegistryKeyEx(RegistryHive.DynData, "HKEY_DYN_DATA");
    public static readonly RegistryKeyEx LocalMachine = new RegistryKeyEx(RegistryHive.LocalMachine, "HKEY_LOCAL_MACHINE");
    public static readonly RegistryKeyEx PerformanceData = new RegistryKeyEx(RegistryHive.PerformanceData, "HKEY_PERFORMANCE_DATA");
    public static readonly RegistryKeyEx Users = new RegistryKeyEx(RegistryHive.Users, "HKEY_USERS");

    private static readonly IList<RegistryKeyEx> RootKeys = new List<RegistryKeyEx>
      {
        ClassesRoot,
        CurrentConfig,
        CurrentUser,
        DynData,
        LocalMachine,
        PerformanceData,
        Users
      };

    private static RegistryKeyEx GetRegistryKey(string keyName, bool createMissingKeys)
    {
      if (keyName == null)
        throw new ArgumentException("Not a valid registry key name", "keyName");

      string[] keys = keyName.Split('\\');

      RegistryKeyEx key = RootKeys.SingleOrDefault(r => r.Name == keys[0]);

      if (key == null)
        throw new ArgumentException("Key name '{0}' does not start with a valid registry root".FormatWith(keyName), "keyName");

      for (int i = 1; i < keys.Length; i++)
      {
        RegistryKeyEx nkey = key.OpenSubKey(keys[i], true);
        if (nkey == null)
        {
          if (!createMissingKeys)
            return null;

          nkey = key.CreateSubKey(keys[i]);
        }

        key = nkey;
      }
      return key;
    }

    public static void SetValue(string keyName, string valueName, object value)
    {
      SetValue(keyName, valueName, value, RegistryValueKind.Unknown);
    }

    public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
    {
      RegistryKeyEx key = GetRegistryKey(keyName, true);
      if (valueName.Length > 255)
        throw new ArgumentException("Value name '{0}' is larger than 255 characters".FormatWith(valueName), "valueName");

      if (key == null)
        throw new ArgumentException("Can't locate key '{0}'".FormatWith(keyName), "keyName");

      key.SetValue(valueName, value, valueKind);
    }

    public static object GetValue(string keyName, string valueName, object defaultValue)
    {
      RegistryKeyEx key = GetRegistryKey(keyName, false);
      if (key == null)
        return defaultValue;

      return key.GetValue(valueName, defaultValue);
    }
  }
}